#include "func_lcd.h"
#include "dri_aip16c22.h"
#include "kernel/os/os.h"
#include <string.h>

#define SEG_0 0
#define SEG_1 1
#define SEG_2 2
#define SEG_3 3
#define SEG_4 4
#define SEG_5 5
#define SEG_6 6
#define SEG_7 7
#define SEG_8 8
#define SEG_9 9
#define SEG_10 10
#define SEG_11 11
#define SEG_12 12
#define SEG_13 13
#define SEG_14 14

//  互斥锁，防止seg_array数据错乱
static OS_Mutex_t lock = {OS_INVALID_HANDLE};

// seg对应的数据全局缓存, 每个seg只有低4bit有效  --- 所有函数需要加锁处理。
static uint8_t seg_array[15] = {0};

// 数字 0 - 9 ， 每个byte的高4bit 和 低4bit，分别对应不同的seg
static uint8_t  num_array[] = {0x3f  ,  0x30 , 0x5b , 0x79, 0x74, 0x6d, 0x6f , 0x31, 0x7f , 0x7d } ;

// ER 两个字母的字模，显示在 hour 的位置
static uint8_t  error_data[] = { 0x4f , 0x77 };

/**
 * @brief 刷新数据时，加锁处理
 * 
 */
static void show_lock(){
	if (!OS_MutexIsValid(&lock))
	{
		OS_MutexCreate(&lock);
	}
	OS_MutexLock(&lock,1000);
}

/**
 * @brief 刷新完数据后，释放锁
 * 
 */
static void show_unlock(){
	if (OS_MutexIsValid(&lock))
	{
		OS_MutexUnlock(&lock);
	}
}

bool lcd_init(){
    memset(seg_array , 0 , sizeof(seg_array)) ;
    return AiP16C22_init(); 
}

// Y1 - Y6
void lcd_battery_show(ICON_LEVEL level){
    show_lock();
    switch (level)
    {
        case LEVEL_NONE:
            {
                // Y1
                seg_array[SEG_1] &= ~(1 << 1) ;  //清零 - 边框
                uint8_t buf = seg_array[SEG_1] << 4  | seg_array[SEG_0] ;
                AiP16C22_write_data( 0x00 ,  &buf, sizeof( buf) );

                // Y2
                seg_array[SEG_9] &= ~(1 << 3) ;
                 buf = seg_array[SEG_9] << 4  | seg_array[SEG_8] ;
                AiP16C22_write_data( 0x04 ,  &buf, sizeof( buf) ); 

                // Y3
                seg_array[SEG_13] &= ~(1 << 3) ;
                 buf = seg_array[SEG_13] << 4  | seg_array[SEG_12] ;
                AiP16C22_write_data( 0x06 ,  &buf, sizeof( buf) ); 

                // Y4
                seg_array[SEG_5] &= ~(1 << 3) ;
                 buf = seg_array[SEG_5] << 4  | seg_array[SEG_4] ;
                AiP16C22_write_data( 0x02 ,  &buf, sizeof( buf) ); 

                // Y5
                seg_array[SEG_3]&= ~(1 << 3) ;
                 buf = seg_array[SEG_3] << 4  | seg_array[SEG_2] ;
                AiP16C22_write_data( 0x01,  &buf, sizeof( buf) );                     

                // Y6
                seg_array[SEG_1] &= ~(1 << 3) ;
                 buf = seg_array[SEG_1] << 4  | seg_array[SEG_0] ;
                AiP16C22_write_data( 0x00 ,  &buf, sizeof( buf) );        
            }
            break;
        case LEVEL_1:
            {   
                    // Y2
                    seg_array[SEG_9] |= (1 << 3)  ;
                    uint8_t buf = seg_array[SEG_9] << 4  | seg_array[SEG_8] ;
                    AiP16C22_write_data( 0x04 ,  &buf, sizeof( buf) ); 
            }
            break;
        case LEVEL_2:
            {
                    // Y2
                    seg_array[SEG_9] |= (1 << 3)  ;
                    uint8_t buf = seg_array[SEG_9] << 4  | seg_array[SEG_8] ;
                    AiP16C22_write_data( 0x04 ,  &buf, sizeof( buf) ); 

                    // Y3
                    seg_array[SEG_13] |= (1 << 3)  ;
                     buf = seg_array[SEG_13] << 4  | seg_array[SEG_12] ;
                    AiP16C22_write_data( 0x06 ,  &buf, sizeof( buf) ); 
            }
            break;  
        case LEVEL_3:
            {
                    // Y2
                    seg_array[SEG_9] |= (1 << 3)  ;
                    uint8_t buf = seg_array[SEG_9] << 4  | seg_array[SEG_8] ;
                    AiP16C22_write_data( 0x04 ,  &buf, sizeof( buf) ); 

                    // Y3
                    seg_array[SEG_13] |= (1 << 3)  ;
                     buf = seg_array[SEG_13] << 4  | seg_array[SEG_12] ;
                    AiP16C22_write_data( 0x06 ,  &buf, sizeof( buf) ); 

                    // Y4
                    seg_array[SEG_5] |= (1 << 3)  ;
                     buf = seg_array[SEG_5] << 4  | seg_array[SEG_4] ;
                    AiP16C22_write_data( 0x02 ,  &buf, sizeof( buf) ); 
            }
            break;   

        case LEVEL_4:
            {
                    // Y2
                    seg_array[SEG_9] |= (1 << 3)  ;
                    uint8_t buf = seg_array[SEG_9] << 4  | seg_array[SEG_8] ;
                    AiP16C22_write_data( 0x04 ,  &buf, sizeof( buf) ); 

                    // Y3
                    seg_array[SEG_13] |= (1 << 3)  ;
                     buf = seg_array[SEG_13] << 4  | seg_array[SEG_12] ;
                    AiP16C22_write_data( 0x06 ,  &buf, sizeof( buf) ); 

                    // Y4
                    seg_array[SEG_5] |= (1 << 3)  ;
                     buf = seg_array[SEG_5] << 4  | seg_array[SEG_4] ;
                    AiP16C22_write_data( 0x02 ,  &buf, sizeof( buf) ); 

                    // Y5
                    seg_array[SEG_3] |= (1 << 3)  ;
                     buf = seg_array[SEG_3] << 4  | seg_array[SEG_2] ;
                    AiP16C22_write_data( 0x01,  &buf, sizeof( buf) );                        
            }
            break;
        case LEVEL_5:
            {
                    // Y2
                    seg_array[SEG_9] |= (1 << 3)  ;
                    uint8_t buf = seg_array[SEG_9] << 4  | seg_array[SEG_8] ;
                    AiP16C22_write_data( 0x04 ,  &buf, sizeof( buf) ); 

                    // Y3
                    seg_array[SEG_13] |= (1 << 3)  ;
                     buf = seg_array[SEG_13] << 4  | seg_array[SEG_12] ;
                    AiP16C22_write_data( 0x06 ,  &buf, sizeof( buf) ); 

                    // Y4
                    seg_array[SEG_5] |= (1 << 3)  ;
                     buf = seg_array[SEG_5] << 4  | seg_array[SEG_4] ;
                    AiP16C22_write_data( 0x02 ,  &buf, sizeof( buf) ); 

                    // Y5
                    seg_array[SEG_3] |= (1 << 3)  ;
                     buf = seg_array[SEG_3] << 4  | seg_array[SEG_2] ;
                    AiP16C22_write_data( 0x01,  &buf, sizeof( buf) );                     

                    // Y6
                    seg_array[SEG_1] |= (1 << 3)  ;
                     buf = seg_array[SEG_1] << 4  | seg_array[SEG_0] ;
                    AiP16C22_write_data( 0x00 ,  &buf, sizeof( buf) );                    
            }
            break;                                        
        default:
            break;
    }

    // Y1
    if (level != LEVEL_NONE) // 显示-边框
    {
            seg_array[SEG_1] |= (1 << 1) ;  //置位 - 边框
            uint8_t buf = seg_array[SEG_1] << 4  | seg_array[SEG_0] ;
            AiP16C22_write_data( 0x00 ,  &buf, sizeof( buf) );
    }
    show_unlock();
}

void lcd_wifi_show(ICON_LEVEL level){
    show_lock();
 switch (level)
    {
    case LEVEL_NONE:
        {
                seg_array[SEG_1] &= ~(1 << 2) ;  //清零 - 边框
                uint8_t buf = seg_array[SEG_1] << 4  | seg_array[SEG_0] ;
    	        AiP16C22_write_data( 0x00 ,  &buf, sizeof( buf) );

                seg_array[SEG_2]  = 0x00 ;  //清零
                buf = seg_array[SEG_3] << 4  | seg_array[SEG_2] ;
                AiP16C22_write_data( 0x01 ,  &buf, sizeof( buf) ); 
        }
        break;
    
    case LEVEL_1:
        {
            seg_array[SEG_2] = 0x04 ;
            uint8_t buf = seg_array[SEG_3] << 4  | seg_array[SEG_2] ;
            AiP16C22_write_data( 0x01 ,  &buf, sizeof( buf) );            
        }
        break;
    case LEVEL_2:
        {
            seg_array[SEG_2] =  0x06;  //置位
            uint8_t buf = seg_array[SEG_3] << 4  | seg_array[SEG_2] ;
            AiP16C22_write_data( 0x01 ,  &buf, sizeof( buf) );            
        }
        break;
    case LEVEL_3:
        {
            seg_array[SEG_2] = 0x07 ;  //置位
            uint8_t buf = seg_array[SEG_3] << 4  | seg_array[SEG_2] ;
            AiP16C22_write_data( 0x01 ,  &buf, sizeof( buf) );            
        }
        break;
    case LEVEL_4:
        {
            seg_array[SEG_2]  = 0x0f;  //置位
            uint8_t buf = seg_array[SEG_3] << 4  | seg_array[SEG_2] ;
            AiP16C22_write_data( 0x01 ,  &buf, sizeof( buf) );            
        }
        break;
    default:
        break;
    }

    if (level != LEVEL_NONE) // 显示-边框
    {
            seg_array[SEG_1] |= (1 << 2) ;  //置位 - 边框
            uint8_t buf = seg_array[SEG_1] << 4  | seg_array[SEG_0] ;
            AiP16C22_write_data( 0x00 ,  &buf, sizeof( buf) );
    }
    show_unlock();
}

// T3
void lcd_upload_show(bool show){
    show_lock();

    if (show)
    {
        seg_array[SEG_0] |= (1 << 2) ;  //置位
        uint8_t buf = seg_array[SEG_1] << 4  | seg_array[SEG_0] ;
    	AiP16C22_write_data( 0x00 ,  &buf, sizeof( buf) );
    }else{
        seg_array[SEG_0] &= ~(1 << 2) ; //清零
        uint8_t buf = seg_array[SEG_1] << 4  | seg_array[SEG_0] ;
    	AiP16C22_write_data( 0x00 ,  &buf, sizeof( buf) );
    }
    show_unlock();
}

// T5
void lcd_dimension_show(bool show){
    show_lock();

    if (show)
    {
        seg_array[SEG_0] |= (1 << 0) ;  //置位
        uint8_t buf = seg_array[SEG_1] << 4  | seg_array[SEG_0] ;
    	AiP16C22_write_data( 0x00 ,  &buf, sizeof( buf) );
    }else{
        seg_array[SEG_0] &= ~(1 << 0) ; //清零
        uint8_t buf = seg_array[SEG_1] << 4  | seg_array[SEG_0] ;
    	AiP16C22_write_data( 0x00 ,  &buf, sizeof( buf) );
    }
    show_unlock();
}

// T6 - 上传和手写需要交换一下
void lcd_pan_show(bool show){
    show_lock();

    if (show)
    {
        seg_array[SEG_0] |= (1 << 1) ;  //置位
        uint8_t buf = seg_array[SEG_1] << 4  | seg_array[SEG_0] ;
    	AiP16C22_write_data( 0x00 ,  &buf, sizeof( buf) );
    }else{
        seg_array[SEG_0] &= ~(1 << 1) ; //清零
        uint8_t buf = seg_array[SEG_1] << 4  | seg_array[SEG_0] ;
    	AiP16C22_write_data( 0x00 ,  &buf, sizeof( buf) );
    }
    show_unlock();
}

// T4
void lcd_ota_show(bool show){
    show_lock();
    
    if (show)
    {
        seg_array[SEG_0] |= (1 << 3) ;  //置位
        uint8_t buf = seg_array[SEG_1] << 4  | seg_array[SEG_0] ;
    	AiP16C22_write_data( 0x00 ,  &buf, sizeof( buf) );
    }else{
        seg_array[SEG_0] &= ~(1 << 3) ; //清零
        uint8_t buf = seg_array[SEG_1] << 4  | seg_array[SEG_0] ;
    	AiP16C22_write_data( 0x00 ,  &buf, sizeof( buf) );
    }
    show_unlock();
}

void lcd_time_show(uint8_t hour , uint8_t min, uint8_t second){
    show_lock();

    // 秒：个位
    uint8_t  second_l_seg_h =  (num_array[second%10 ] >> 4) & 0x0f ;
    uint8_t  second_l_seg_l  = num_array[second%10 ] &0x0f  ;
   // 秒：十位
    uint8_t  second_h_seg_h =  (num_array[second/10 ] >> 4) & 0x0f ;
    uint8_t  second_h_seg_l  = num_array[second/10 ] &0x0f  ;

    printf("second_l_seg_h = %02x , second_l_seg_l = %02x \n", second_l_seg_h , second_l_seg_l);
    seg_array[SEG_3] &= ~(0x07) ; //清零低三位
    seg_array[SEG_3] |= second_l_seg_h ;  //置位
    seg_array[SEG_4]  =  second_l_seg_l ;

    seg_array[SEG_5] &= ~(0x07) ; //清零低三位
    seg_array[SEG_5] |= second_h_seg_h ;  //置位
    seg_array[SEG_6]  =  second_h_seg_l ;

    // 秒：个位 -- 低4bit
    uint8_t buf = seg_array[SEG_3] << 4  | seg_array[SEG_2] ;
    AiP16C22_write_data( 0x01 ,  &buf, sizeof( buf) );
    // 秒：个位 -- 高4bit + 十位低4bit
    buf = seg_array[SEG_5] << 4  | seg_array[SEG_4] ;
    AiP16C22_write_data( 0x02 ,  &buf, sizeof( buf) );

    // 分：个位
    uint8_t  min_l_seg_h =  (num_array[min%10 ] >> 4) & 0x0f ;
    uint8_t  min_l_seg_l  = num_array[min%10 ] &0x0f  ;
   // 分：十位
    uint8_t  min_h_seg_h =  (num_array[min/10 ] >> 4) & 0x0f ;
    uint8_t  min_h_seg_l  = num_array[min/10 ] &0x0f  ;
    seg_array[SEG_7] &= ~(0x07) ; //清零低三位
    seg_array[SEG_7] |= min_l_seg_h ;  //置位
    seg_array[SEG_7] |= (1<<3) ;  //置位 - 显示点符号
    seg_array[SEG_8]  =  min_l_seg_l ;

    seg_array[SEG_9] &= ~(0x07) ; //清零低三位
    seg_array[SEG_9] |= min_h_seg_h ;  //置位
    seg_array[SEG_10]  =  min_h_seg_l ;

    // 分：个位 -- 低4bit + 十位高4bit
    buf = seg_array[SEG_7] << 4  | seg_array[SEG_6] ;
    AiP16C22_write_data( 0x03 ,  &buf, sizeof(  buf ) );

    buf = seg_array[SEG_9] << 4  | seg_array[SEG_8] ;
    AiP16C22_write_data( 0x04 ,  &buf, sizeof(  buf ) );


    // 时：个位
    uint8_t  hour_l_seg_h =  (num_array[hour%10 ] >> 4) & 0x0f ;
    uint8_t  hour_l_seg_l  = num_array[hour%10 ] &0x0f  ;
   // 时：十位
    uint8_t  hour_h_seg_h =  (num_array[hour/10 ] >> 4) & 0x0f ;
    uint8_t  hour_h_seg_l  = num_array[hour/10 ] &0x0f  ;
    seg_array[SEG_11] &= ~(0x07) ; //清零低三位
    seg_array[SEG_11] |= hour_l_seg_h ;  //置位
    seg_array[SEG_11] |= (1<<3) ;  //置位 - 显示点符号
    seg_array[SEG_12]  =  hour_l_seg_l ;

    seg_array[SEG_13] &= ~(0x07) ; //清零低三位
    seg_array[SEG_13] |= hour_h_seg_h ;  //置位
    seg_array[SEG_14]  =  hour_h_seg_l ;

    buf = seg_array[SEG_11] << 4  | seg_array[SEG_10] ;
    AiP16C22_write_data( 0x05 ,  &buf , sizeof(  buf ) );

    buf = seg_array[SEG_13] << 4  | seg_array[SEG_12] ;
    AiP16C22_write_data( 0x06 ,  &buf , sizeof(  buf ) );

    AiP16C22_write_data( 0x07 ,  &seg_array[SEG_14] , sizeof(  seg_array[SEG_14] ) );

    show_unlock();
}


void lcd_errorcode_show(uint8_t code){
    show_lock();

    // 分：个位
    uint8_t  min_l_seg_h =  (num_array[code%10 ] >> 4) & 0x0f ;
    uint8_t  min_l_seg_l  = num_array[code%10 ] &0x0f  ;
   // 分：十位
    uint8_t  min_h_seg_h =  (num_array[code/10 ] >> 4) & 0x0f ;
    uint8_t  min_h_seg_l  = num_array[code/10 ] &0x0f  ;
    seg_array[SEG_7] &= ~(0x07) ; //清零低三位
    seg_array[SEG_7] |= min_l_seg_h ;  //置位
    seg_array[SEG_8]  =  min_l_seg_l ;

    seg_array[SEG_9] &= ~(0x07) ; //清零低三位
    seg_array[SEG_9] |= min_h_seg_h ;  //置位
    seg_array[SEG_10]  =  min_h_seg_l ;

    // 分：个位 -- 低4bit + 十位高4bit
    uint8_t buf = seg_array[SEG_7] << 4  | seg_array[SEG_6] ;
    AiP16C22_write_data( 0x03 ,  &buf, sizeof(  buf ) );

    buf = seg_array[SEG_9] << 4  | seg_array[SEG_8] ;
    AiP16C22_write_data( 0x04 ,  &buf, sizeof(  buf ) );

    uint8_t E = error_data[0]  ;
    uint8_t R = error_data[1] ;
    seg_array[SEG_11] &= ~(0x07) ; //清零低三位
    seg_array[SEG_11] |=  (R >>4) & 0x0f ;  //置位
    seg_array[SEG_12]  =  (R ) & 0x0f  ;

    seg_array[SEG_13] &= ~(0x07) ; //清零低三位
    seg_array[SEG_13] |= (E >>4) & 0x0f ;  //置位
    seg_array[SEG_14]  =   (E ) & 0x0f  ;

    buf = seg_array[SEG_11] << 4  | seg_array[SEG_10] ;
    AiP16C22_write_data( 0x05 ,  &buf , sizeof(  buf ) );

    buf = seg_array[SEG_13] << 4  | seg_array[SEG_12] ;
    AiP16C22_write_data( 0x06 ,  &buf , sizeof(  buf ) );

    AiP16C22_write_data( 0x07 ,  &seg_array[SEG_14] , sizeof(  seg_array[SEG_14] ) );    

    show_unlock();
}

void lcd_clean_time(){
    show_lock();
    
    // 秒
    seg_array[SEG_3] &= ~(0x07) ; //清零低三位
    seg_array[SEG_4] &= ~(0x0f) ;
    seg_array[SEG_5] &= ~(0x07) ; //清零低三位
    seg_array[SEG_6] &= ~(0x0f) ;

    // 分
    seg_array[SEG_7] &= ~(0x0f) ; //清零低三位
    seg_array[SEG_8] &= ~(0x0f) ;
    seg_array[SEG_9] &= ~(0x07) ; //清零低三位
    seg_array[SEG_10] &= ~(0x0f) ;
    
    // 时
    seg_array[SEG_11] &= ~(0x0f) ; //清零低三位
    seg_array[SEG_12] &= ~(0x0f) ;
    seg_array[SEG_13] &= ~(0x07) ; //清零低三位
    seg_array[SEG_14] &= ~(0x0f) ;    

    // 秒：个位 -- 低4bit
    uint8_t buf = seg_array[SEG_3] << 4  | seg_array[SEG_2] ;
    AiP16C22_write_data( 0x01 ,  &buf, sizeof( buf) );
    // 秒：个位 -- 高4bit + 十位低4bit
    buf = seg_array[SEG_5] << 4  | seg_array[SEG_4] ;
    AiP16C22_write_data( 0x02 ,  &buf, sizeof( buf) );

    // 分：个位 -- 低4bit + 十位高4bit
    buf = seg_array[SEG_7] << 4  | seg_array[SEG_6] ;
    AiP16C22_write_data( 0x03 ,  &buf, sizeof(  buf ) );

    buf = seg_array[SEG_9] << 4  | seg_array[SEG_8] ;
    AiP16C22_write_data( 0x04 ,  &buf, sizeof(  buf ) );

    buf = seg_array[SEG_11] << 4  | seg_array[SEG_10] ;
    AiP16C22_write_data( 0x05 ,  &buf , sizeof(  buf ) );

    buf = seg_array[SEG_13] << 4  | seg_array[SEG_12] ;
    AiP16C22_write_data( 0x06 ,  &buf , sizeof(  buf ) );

    AiP16C22_write_data( 0x07 ,  &seg_array[SEG_14] , sizeof(  seg_array[SEG_14] ) );

    show_unlock();
}


void lcd_mock_test(){
    lcd_init();
	lcd_ota_show(true);
	lcd_pan_show(true);
	lcd_upload_show(true);
	lcd_dimension_show(true);

    for (size_t i = 0; i < 5; i++)
    {
        lcd_wifi_show(i);
        OS_Sleep(1);
    }
    
	for (size_t i = 0; i < 6; i++)
    {
    	lcd_battery_show(i);
        OS_Sleep(1);
    }

    lcd_ota_show(false);
	lcd_pan_show(true);
	lcd_upload_show(false);
	lcd_dimension_show(true);

    for (size_t i = 0; i < 10; i++)
    {
            lcd_time_show(i , i , i);
            OS_Sleep(1);
    }

    lcd_clean_time();
    OS_Sleep(1);
    lcd_errorcode_show(1);
    OS_Sleep(2);

    for (size_t i = 10; i < 20; i++)
    {
            lcd_time_show(i , i , i);
            OS_Sleep(1);
    }

}
